package com.breeze.socketdemo.tcp;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;

import androidx.annotation.NonNull;

import com.breeze.socketdemo.MainActivity;
import com.breeze.socketdemo.utils.MyUtil;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;

public class TcpClient {
    private static final String TAG = "TcpClient";
    private static final int MSG_SEND = 0;
    private Socket mSocket;
    private PrintWriter mPrintWriter;
    private boolean mRunning;
    private Handler mSendHandler;
    private String mHost;
    private int mPort;
    private HandlerThread mSendThread;

    private Handler mainHandler;

    public TcpClient(Handler handler) {
        mainHandler = handler;
    }

    public void connect(String host, int port) {
        mHost = host;
        mPort = port;
        mRunning = true;
        new ConnectThread().start();
    }

    public void close() {
        mRunning = false;
        mSendThread.quit();
    }

    public void sendMsg(final String msg) {
        Message.obtain(mSendHandler, MSG_SEND, msg).sendToTarget();
    }

    class ConnectThread extends Thread {

        @Override
        public void run() {
            super.run();
            mRunning = true;
            try {
                Log.i(TAG, "connecting...");
                mSocket = new Socket(mHost, mPort);
                Log.i(TAG, "connected");
                mSendThread = new HandlerThread("client_send");
                mSendThread.start();
                mSendHandler = new Handler(mSendThread.getLooper(), new SendMessageCallback());
                mPrintWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream())));
                new ReceiveThread(mSocket).start();
            } catch (IOException e) {
                e.printStackTrace();
                Log.e(TAG, "client exception=" + e.getMessage());
            }
        }
    }

    class SendMessageCallback implements Handler.Callback {

        @Override
        public boolean handleMessage(@NonNull Message msg) {
            int what = msg.what;
            switch (what) {
                case MSG_SEND:
                    sendMessage((String) msg.obj);
                    break;
            }
            return false;
        }

        private void sendMessage(String msg) {
            mPrintWriter.println(msg);
            mPrintWriter.flush();
        }
    }

    class ReceiveThread extends Thread {
        private Socket socket;

        public ReceiveThread(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            super.run();
            if (socket == null) {
                return;
            }
            BufferedReader br = null;
            try {
                br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));
                while (mRunning) {
                    String msg = br.readLine();
                    Log.i(TAG, "receive from server message:" + msg);
                    // 当服务端断开时会收到null消息
                    if (msg == null) {
                        break;
                    }
                    if (mainHandler != null) {
                        Message.obtain(mainHandler, MainActivity.MSG_RECEIVE_FROM_SERVER, msg).sendToTarget();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                MyUtil.close(br, socket);
            }
        }
    }
}
